package net.nohaven.proj.javeau.utils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class Utils {
	private Utils() {
	}

	public final static int getRepresentationBytes(long l) {
		if (l < 0)
			return -1;
		int ret = 0;
		do {
			ret++;
			l >>= 8;
		} while (l != 0);
		return ret;
	}

	public final static int encodeLittleEndian(long l, byte[] rep, int off) {
		int len = getRepresentationBytes(l);
		for (int i = 0; i < len; i++)
			rep[i + off] = (byte) (l >> (8 * i));
		return len;
	}

	public final static long decodeLittleEndian(byte[] rep, int off, int len) {
		long l = 0;
		for (int i = 0; i < len; i++)
			l |= ((long) (rep[i + off] & 0xFF)) << (8 * i);
		return l;
	}

	public final static void encodeLittleEndian32(int l, byte[] rep, int off) {
		rep[off] = (byte) l;
		rep[1 + off] = (byte) (l >> 8);
		rep[2 + off] = (byte) (l >> 16);
		rep[3 + off] = (byte) (l >> 24);
	}

	public final static int decodeLittleEndian32(byte[] rep, int off) {
		return (rep[off] & 0xFF) | ((rep[1 + off] & 0xFF) << 8)
				| ((rep[2 + off] & 0xFF) << 16) | ((rep[3 + off] & 0xFF) << 24);
	}

	public final static void encodeLittleEndian64(long l, byte[] rep, int off) {
		rep[0 + off] = (byte) l;
		rep[1 + off] = (byte) (l >> 8);
		rep[2 + off] = (byte) (l >> 16);
		rep[3 + off] = (byte) (l >> 24);
		rep[4 + off] = (byte) (l >> 32);
		rep[5 + off] = (byte) (l >> 40);
		rep[6 + off] = (byte) (l >> 48);
		rep[7 + off] = (byte) (l >> 56);
	}

	public final static long decodeLittleEndian64(byte[] rep, int off) {
		return (rep[off] & 0xFF) | ((rep[1 + off] & 0xFF) << 8)
				| ((rep[2 + off] & 0xFF) << 16) | ((rep[3 + off] & 0xFF) << 24)
				| ((rep[4 + off] & 0xFF) << 32) | ((rep[5 + off] & 0xFF) << 40)
				| ((rep[6 + off] & 0xFF) << 48) | ((rep[7 + off] & 0xFF) << 56);
	}

	//	public final static void encodeBigEndian32(int l, byte[] rep, int off) {
	//		rep[off] = (byte) (l >> 24);
	//		rep[1 + off] = (byte) (l >> 16);
	//		rep[2 + off] = (byte) (l >> 8);
	//		rep[3 + off] = (byte) l;
	//	}

	//	public final static int decodeBigEndian32(byte[] rep, int off) {
	//		return (rep[3 + off] & 0xFF) | ((rep[2 + off] & 0xFF) << 8)
	//				| ((rep[1 + off] & 0xFF) << 16) | ((rep[off] & 0xFF) << 24);
	//	}

	//	public final static void encodeBigEndian64(long l, byte[] rep, int off) {
	//		rep[0 + off] = (byte) (l >> 56);
	//		rep[1 + off] = (byte) (l >> 48);
	//		rep[2 + off] = (byte) (l >> 40);
	//		rep[3 + off] = (byte) (l >> 32);
	//		rep[4 + off] = (byte) (l >> 24);
	//		rep[5 + off] = (byte) (l >> 16);
	//		rep[6 + off] = (byte) (l >> 8);
	//		rep[7 + off] = (byte) l;
	//	}

	//	public final static long decodeBigEndian64(byte[] rep, int off) {
	//		return (rep[7 + off] & 0xFF) | ((rep[6 + off] & 0xFF) << 8)
	//				| ((rep[5 + off] & 0xFF) << 16) | ((rep[4 + off] & 0xFF) << 24)
	//				| ((rep[3 + off] & 0xFF) << 32) | ((rep[2 + off] & 0xFF) << 40)
	//				| ((rep[1 + off] & 0xFF) << 48) | ((rep[0 + off] & 0xFF) << 56);
	//	}

	//	public final static long rotateLeft(long word, int amount) {
	//		return (word << amount) | (word >>> (64 - amount));
	//	}

	//	public final static int rotateLeft(int word, int amount) {
	//		return (word << amount) | (word >>> (32 - amount));
	//	}

	//	public final static byte rotateLeft(byte word, int amount) {
	//		return (byte) ((word << amount) | (word >>> (8 - amount)));
	//	}

	//	public final static int rotateRight(int word, int amount) {
	//		return (word << (32 - amount)) | (word >>> amount);
	//	}

	public static int copy(InputStream input, OutputStream output)
			throws IOException {
		byte[] buffer = new byte[4192];
		int count = 0;
		int n = 0;
		while ((n = input.read(buffer)) > 0) {
			output.write(buffer, 0, n);
			count += n;
		}
		return count;
	}

	public static boolean isEmpty(String s) {
		return (s == null) || (s.trim().length() == 0);
	}

	public static boolean isEmpty(char[] c) {
		return (c == null) || (c.length == 0);
	}

	private static final char[] HEX = new char[] { '0', '1', '2', '3', '4',
			'5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

	public static String bytes2Hex(byte[] bytes) {
		StringBuffer sb = new StringBuffer();
		for (byte b : bytes) {
			sb.append(HEX[(b >> 4) & 0xF]);
			sb.append(HEX[b & 0xF]);
		}
		return sb.toString();
	}

	private static byte c2i(char c) {
		if (c >= '0' && c <= '9')
			return (byte) (c - '0');
		if (c >= 'A' && c <= 'F')
			return (byte) (c - 'A');
		return -1;
	}

	public static byte[] hex2Bytes(String hex) {
		char[] chex = hex.toUpperCase().toCharArray();
		byte[] ret = new byte[hex.length() / 2];
		for (int i = 0; i < ret.length; i++) {
			ret[i] = (byte) (c2i(chex[i * 2 + 1]) << 4);
			ret[i] |= c2i(chex[i * 2 + 1]);
		}
		return ret;
	}

	public static int alignToWord(int num, int wordSize) {
		while (num % wordSize != 0)
			num++;
		return num;
	}
}
